package descentFly.away3D4.controller
{
	import UIFree.ObjectEvent;
	
	import away3d.entities.Mesh;
	import away3d.events.Object3DEvent;
	
	import descentFly.away3D4.chips.df_chipAway;
	import descentFly.away3D4.chips.df_chipModel;
	import descentFly.away3D4.df_awaySpace;
	import descentFly.away3D4.df_path;
	import descentFly.chips.df_chip;
	import descentFly.controller.FlyController;
	import descentFly.controller.df_robotController;
	import descentFly.df_space;
	import descentFly.df_utils;
	import descentFly.jiglib.utils;
	import descentFly.weaponts.IBullet;
	
	import flash.display.Stage;
	import flash.events.EventDispatcher;
	import flash.events.TimerEvent;
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	import flash.utils.Timer;
	
	import jiglib.math.JMatrix3D;
	
	import space.sp_utils;
	
	public class df_robotAway extends df_robotController {
		
		public static const FIELD_DANGEROUSDISTANCEDEC	: String = 'dangerousDistanceDec';
		public static const FIELD_DANGERACTION			: String = 'dangerAction';
		public static const FIELD_MAXDISTANCE			: String = 'maxDistance';

		public static const DEFAULT_MAXDISTANCE			: Number = 1000;

		private var _lookMat		: Matrix3D;
		private var _lookVec		: Vector3D;
		private var _lookChip		: df_chipAway;
		private var _path			: df_path;
		private var _patrolIndex	: Number;
		
		public static function create(a_stage	: Stage,
									  a_space	: df_space,
									  a_options: Object=null): df_robotController {
			return new df_robotAway(a_stage, a_space, a_options);
		}
		
		override public function setBody(a_body:df_chip):void {
			super.setBody(a_body);
			bodyAway.addEventListener(df_chip.BULLETHIT, doBulletHit);
		}
		
		override protected function removeEvents():void {
			bodyAway.removeEventListener(df_chip.BULLETHIT, doBulletHit);
			super.removeEvents();
		}
		
		protected function doBulletHit(e: ObjectEvent): void {
			if ((e.object.bullet as IBullet).chip == Space.myChip)
				if (checkSee(false)) state = df_robotController.STATE_ATACK;
		}
		
		public function df_robotAway(a_stage:Stage, a_space	: df_space, a_options: Object=null) {
			sp_utils.checkParam(a_options, FIELD_MAXDISTANCE, DEFAULT_MAXDISTANCE);
			super(a_stage, a_space, a_space, a_options);
		}
		
		public function get awaySpace(): df_awaySpace {
			return dispatcher as df_awaySpace;
		}
		
		protected function get bodyAway(): df_chipAway {
			return body as df_chipAway;
		}
		
/*		protected function lookCalculate(actorAway: df_chipAway): void {
			if (body && bodyAway.body) {
				var pos: Vector3D = bodyAway.body.currentState.position;
				_lookVec = actorAway.body.currentState.position.subtract(pos);
				_lookMat = sp_utils.lookAt(new Vector3D(), _lookVec);
			}
		}*/
		
		override protected function checkSee(isDir: Boolean=true): Boolean {
			var isCheckSee: Boolean = see;
			
			bodyAway.actorForEach(function(actorAway: df_chipAway): void {
				if (actorAway.noActiveSphere && (_lookChip == actorAway))
					isCheckSee = false;
				else if (bodyAway.body.isActive || actorAway.body.isActive) {
					isCheckSee = false;
					
					var pos: Vector3D = bodyAway.body.currentState.position;
					var v_lookVec: Vector3D = actorAway.body.currentState.position.subtract(pos);
					_lookChip = null;
					
					if ((v_lookVec.length <= options.maxDistance) && !isCheckSee && awaySpace.env && (awaySpace.env.numChildren > 0)) {
						
						if (!isDir || 
							(v_lookVec.dotProduct(bodyAway.body.currentState.orientation.transformVector(Vector3D.Z_AXIS)) > 0)) { 
							// isDir: Если актер в пространстве по направлению движения
							
							var result: Object = awaySpace.envRayTest(bodyAway.body.currentState.position, actorAway.body.currentState.position);
							if (result == null) {
								_lookMat 	= sp_utils.lookAt(new Vector3D(), v_lookVec);
								_lookVec 	= v_lookVec;
								_lookChip	= actorAway;
								isCheckSee 	= true;
							} 
						} 
					}
				}
			});
				
			return isCheckSee;
		}
		
		protected function setTransform(data: Object): void {
			var lookMat: Matrix3D = sp_utils.lookAt(new Vector3D(), data.dir);
			bodyAway.body.setOrientation(lookMat);
			bodyAway.body.currentState.position = data.position;
		}
		
		override protected function setState(a_state: int): void {
			super.setState(a_state);
			if ((state != df_robotController.STATE_ATACK) && 
				(bodyAway.currentWeapont && bodyAway.currentWeapont.isFire)) bodyAway.fire(false);
			else if (state == df_robotController.STATE_ATACK) bodyAway.fire(true);
			
			if (state == df_robotController.STATE_PATROL) {
				if (!_path) {
					var event: Object = {
						result		: null,
						controller	: this,
						pathIndex	: options.pathIndex,
						pathID		: options.pathID
					}
					awaySpace.dispatchEvent(new ObjectEvent(df_awaySpace.GET_PATHPATROL, event));
					_path = event.result;
				}
				resetStartPosition();
			}
		}
		
		override protected function resetStartPosition(): void {
			if ((state == df_robotController.STATE_PATROL) && _path) {
				var index: int = _path.getNearestPoint(bodyAway.body.currentState.position);
				if (index > -1) {
				//trace('point: ' + index);
					_patrolIndex = _path.percentFromIndex(index);
					setTransform(_path.getDataFromPercent(_patrolIndex));
				} else _patrolIndex = 0;
			} else super.resetStartPosition();
		}
		
		override protected function patrol(): void {
			if (body && _path) {
				impulseFromPath(_patrolIndex);
				_patrolIndex = (_patrolIndex + (bodyAway.options.pathSpeed/_path.getFullDistance()) * 100) % 100;
			}
		}
		
		public function impulseFromPath(a_patrolIndex: Number): void {
			var current: Object = _path.getDataFromPercent(a_patrolIndex/100);
			var dir: Vector3D = current.position.subtract(bodyAway.body.currentState.position);
			var lookMat: Matrix3D = sp_utils.lookAt(new Vector3D(), dir);
			
			bodyAway.body.setOrientation(lookMat);
			_moveRequest = dir.length;
		}
		
		public function get patrolIndex(): Number {
			return _patrolIndex;
		}
		
		override protected function atack():void {
			drive();
			if (options[FIELD_DANGEROUSDISTANCEDEC]) {
				if (_lookChip && !_lookChip.noActiveSphere && _lookChip.attackable && 
					(_lookVec.length <= (_lookChip.attackableRadius + bodyAway.attackableRadius * 1.5))) {
					(bodyAway as df_chipModel).beginAction(options[FIELD_DANGERACTION]);
					_lookChip.damageForce(options[FIELD_DANGEROUSDISTANCEDEC], bodyAway);
				}
			}
			super.atack();
		}
		
		override protected function drive(): void {
			if (_lookMat) {
				tracking();
				_moveRequest += (bodyAway.options.maxSpeed - _moveRequest) * Space.options.chipACCEL;
			}
			super.drive();
		}
		
		override protected function tracking(): void {
			if (_lookMat) {
				bodyAway.body.setOrientation(Matrix3D.interpolate(bodyAway.body.currentState.orientation, _lookMat, Space.options.chipACCEL));
			}
			super.tracking();
		} 
	}
}